package nc.bs.hrpbm.budgetmake.util;

import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.jdbc.framework.processor.BeanListProcessor;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.jdbc.framework.processor.MapProcessor;
import nc.md.persist.framework.MDPersistenceService;
import nc.mddb.baseutil.MDDAOUtil;
import nc.pubitf.initgroup.InitGroupQuery;
import nc.pubitf.para.SysInitQuery;
import nc.vo.arap.bx.util.BXUtil;
import nc.vo.hrpbm.budgetadjust.AggBudgetAdjustVO;
import nc.vo.hrpbm.budgetadjust.BudgetAdjustDetailVO;
import nc.vo.hrpbm.budgetmake.AggBudgetMakeVO;
import nc.vo.hrpbm.budgetmake.BudgetMakeDetailVO;
import nc.vo.hrpbm.budgetmake.BudgetMakeVO;
import nc.vo.hrpbm.budgetreply.AggBudgetReplyVO;
import nc.vo.hrpbm.budgetreply.BudgetReplyDetailVO;
import nc.vo.hrpbm.budgetreply.BudgetReplyVO;
import nc.vo.hrpbm.budgettask.Budgettask;
import nc.vo.hrppl.pjapplication.PJApplHVO;
import nc.vo.pub.BusinessException;
import nc.vo.pub.ISuperVO;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pub.lang.UFDouble;
import nccloud.commons.lang.StringUtils;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

// 预算编制方案中启用了“项目”维度时增加的控制 项目库相关参数校验
public class CheckAboutHrppl {

    private static BaseDAO baseDAO;

    private static BaseDAO getBaseDAO() {
        if (baseDAO == null) {
            baseDAO = new BaseDAO();
        }

        return baseDAO;
    }

    // 是否安装了项目库 并启用
    private static boolean isInstalledAndEnabledHrppl() throws BusinessException {
        boolean flag = (BXUtil.isProductTbbInstalled("M027")
                && InitGroupQuery.isEnabled(InvocationInfoProxy.getInstance().getGroupId(), "M027"));
        return flag;
    }

    public static void check_adjustmny(AggBudgetAdjustVO vo) throws BusinessException {
        if (vo.getParentVO().getDef3().equals("1001A110000000GN81UH")) {
            Map<String, UFDouble> adjustmny = new HashMap<String, UFDouble>();
            ISuperVO[] children = vo.getChildren(BudgetAdjustDetailVO.class);
            for (int i = 0; i < children.length; i++) {
                BudgetAdjustDetailVO child = (BudgetAdjustDetailVO) children[i];
                if (adjustmny.containsKey(child.getPk_fundsource())) {
                    adjustmny.put(child.getPk_fundsource(), adjustmny.get(child.getPk_fundsource()).add(child.getAmount_adjust()));
                } else {
                    adjustmny.put(child.getPk_fundsource(), child.getAmount_adjust());
                }
            }
            for (String key : adjustmny.keySet()) {
                if (adjustmny.get(key).compareTo(UFDouble.ZERO_DBL) != 0) {
                    throw new BusinessException("[若调整类型为调剂时，相同资金来源的调整金额，合计数也必须为0，请检查数据]");
                }
            }
        }
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    public static void check_budgetMake(AggBudgetMakeVO vo) throws BusinessException {
        // 是否安装了项目库 并启用
        if (!isInstalledAndEnabledHrppl())
            return;
        // 支出预算、资本预算及采购预算的编制单（一上，二上） HRPXM001+HRPXM002或HRPXM001+HRPXM003同时启用
        if (vo.getParentVO().getTranstype().equals("BM20-Cxx-CD-YS02")
                || vo.getParentVO().getTranstype().equals("BM20-Cxx-CD-YS03")
                || vo.getParentVO().getTranstype().equals("BM20-Cxx-CD-YS04")) {
            // 判断是否预算编制方案中开启了 项目 维度
            String flag = (String) getBaseDAO()
                    .executeQuery("SELECT hrpbm_budgetschemedetail.ISUSING as flag FROM hrpbm_budgetscheme \r\n"
                            + "left join HRPBM_BUDGETTYPE on hrpbm_budgetscheme.pk_budgettype = HRPBM_BUDGETTYPE.pk_budgettype\r\n"
                            + "left join hrpbm_budgetschemedetail on hrpbm_budgetscheme.PK_BUDGETSCHEME  = hrpbm_budgetschemedetail.PK_BUDGETSCHEME\r\n"
                            + "left join HRPBM_BUDGETDIM on HRPBM_BUDGETDIM.PK_BUDGETDIM = hrpbm_budgetschemedetail.PK_BUDGETDIM\r\n"
                            + " WHERE  hrpbm_budgetscheme.pk_group = '" + vo.getParentVO().getPk_group()
                            + "' and hrpbm_budgetscheme.nyear = '" + vo.getParentVO().getNyear()
                            + "' and HRPBM_BUDGETTYPE.code = '"
                            + vo.getParentVO().getTranstype().substring(vo.getParentVO().getTranstype().length() - 4)
                            + "' and HRPBM_BUDGETDIM.name = '项目'", new ColumnProcessor());

            if (flag.equals("N")) {
                return;
            }
            if (vo.getParentVO().getApprovestatus() == 1) { //批复单提交/审批 后 会回写数据到编制单 此时不走校验
                return;
            }

            UFBoolean HRPXM001_Boolean = SysInitQuery.getParaBoolean(vo.getParentVO().getPk_group(), "HRPXM001");
            UFBoolean HRPXM002_Boolean = SysInitQuery.getParaBoolean(vo.getParentVO().getPk_group(), "HRPXM002");
            UFBoolean HRPXM003_Boolean = SysInitQuery.getParaBoolean(vo.getParentVO().getPk_group(), "HRPXM003");

            if (!HRPXM001_Boolean.booleanValue()) { // 如果不开启该参数 则不校验
                return;
            }

            // 1上2上 taskstage
            if (vo.getParentVO().getTaskstage() == 1 || vo.getParentVO().getTaskstage() == 3) {

                ISuperVO[] children = vo.getChildren(BudgetMakeDetailVO.class);
                // 表体会存在同一项目不同维度的数据 需要先把同一项目的金额合并 再校验
                HashMap<String, BudgetMakeDetailVO> hashMap = new HashMap<String, BudgetMakeDetailVO>();

                if (children != null && children.length > 0) {
                    for (int i = 0; i < children.length; i++) {
                        BudgetMakeDetailVO child = (BudgetMakeDetailVO) children[i];
                        if (child.getStatus() == 3) {
                            continue;
                        }
                        if (hashMap.get(child.getPk_project()) == null) {
                            // 此处用clone的vo 不要修改原数据
                            BudgetMakeDetailVO clone = (BudgetMakeDetailVO) child.clone();
                            hashMap.put(child.getPk_project(), clone);
                        } else {
                            BudgetMakeDetailVO detailVO = hashMap.get(child.getPk_project());
                            detailVO.setAmount_firstup(detailVO.getAmount_firstup() == null ? UFDouble.ZERO_DBL
                                    : detailVO.getAmount_firstup()
                                    .add(child.getAmount_firstup() == null ? UFDouble.ZERO_DBL
                                            : child.getAmount_firstup()));
                            if (vo.getParentVO().getTaskstage() == 3) {
                                detailVO.setAmount_secondup(detailVO.getAmount_secondup() == null ? UFDouble.ZERO_DBL
                                        : detailVO.getAmount_secondup()
                                        .add(child.getAmount_secondup() == null ? UFDouble.ZERO_DBL
                                                : child.getAmount_secondup()));
                            }
                        }
                    }
                }

                for (Map.Entry<String, BudgetMakeDetailVO> entry : hashMap.entrySet()) {
                    BudgetMakeDetailVO child = entry.getValue();
                    String pk_project = child.getPk_project();
                    // 引用自项目库的项目 则项目档案和项目库的主键都是这个
                    PJApplHVO pjApplHVO = (PJApplHVO) getBaseDAO().retrieveByPK(PJApplHVO.class, pk_project);

//							PJApplHVO pjApplHVO = findByPk(PJApplHVO.class, pk_project);
                    if (pjApplHVO == null) {
//						throw new BusinessException("当前表体引用的项目库项目不存在,请联系项目库相关人员");
                        continue;
                    }
                    UFDouble pjtotalcost = pjApplHVO.getPjtotalcost(); // 项目库项目总经费
                    if (pjtotalcost == null) {
                        pjtotalcost = UFDouble.ZERO_DBL;
                    }
                    if (pjApplHVO.getTranstype().equals("PL01-Cxx-PJ01")) { // PL01-Cxx-PJ01 常规
                        if (HRPXM002_Boolean.booleanValue()) {
                            // 预算编制单引用了项目库的“常规项目”进行预算编制，保存时要进行验证：当年预算编制金额不能超过项目库项目总经费(pjtotalcost)

                            // 取当前保存单据的预算年度
                            Integer nyear = Integer.valueOf(vo.getParentVO().getNyear());
                            // 项目对应的预算编制金额 查询的时候排除掉当前单据的
                            Map<String, Object> map = (Map<String, Object>) getBaseDAO().executeQuery(
                                    " SELECT sum(hrpbm_budgetmakedetail.amount_firstup) first,sum(hrpbm_budgetmakedetail.amount_secondup) second \r\n"
                                            + "FROM hrpbm_budgetmakedetail LEFT JOIN hrpbm_budgetmake on hrpbm_budgetmakedetail.pk_budgetmake = hrpbm_budgetmake.pk_budgetmake\r\n"
                                            + "where hrpbm_budgetmakedetail.dr = 0 and hrpbm_budgetmakedetail.pk_project = '" + pk_project
                                            + "' AND hrpbm_budgetmake.TRANSTYPE = '" + vo.getParentVO().getTranstype()
                                            + "' AND hrpbm_budgetmake.taskstage = '"
                                            + vo.getParentVO().getTaskstage().toString()
                                            + "' and hrpbm_budgetmakedetail.nyear = '" + nyear
                                            + "' AND hrpbm_budgetmakedetail.PK_BUDGETMAKE != '"
                                            + vo.getParentVO().getPrimaryKey() + "' ",
                                    new MapProcessor());

                            // 项目预算金额
                            UFDouble yusuan = UFDouble.ZERO_DBL;
                            if (vo.getParentVO().getTaskstage() == 1) {
                                Object object = map.get("first");
                                if (object != null) {
                                    // 加上当前单据的
                                    yusuan = new UFDouble(object.toString()).add(child.getAmount_firstup());
                                } else {
                                    // 只计算当前单据
                                    yusuan = child.getAmount_firstup();
                                }
                            } else if (vo.getParentVO().getTaskstage() == 3) {
                                Object object = map.get("second");
                                if (object != null) {
                                    // 加上当前单据的
                                    yusuan = new UFDouble(object.toString()).add(child.getAmount_secondup());
                                } else {
                                    // 只计算当前单据
                                    yusuan = child.getAmount_secondup();
                                }
                            }
                            UFDouble result = UFDouble.ZERO_DBL;
                            result = yusuan.sub(pjtotalcost);
                            if (result.doubleValue() > 0) {
                                throw new BusinessException(
                                        "[" + pjApplHVO.getPjname() + "]项目预算金额:" + new UFDouble(yusuan.doubleValue(), 2)
                                                + "元已超过项目总经费:" + new UFDouble(result.doubleValue(), 2) + "元");
                            }
                        }
                    } else { // 非常规项目的校验
                        if (HRPXM003_Boolean.booleanValue()) {
                            String paraString = SysInitQuery.getParaString(vo.getParentVO().getPk_group(), "HRPXM007");
                            // 累计预算金额不能超过项目库项目总经费

                            // 业务年:业务日期对应的年度
                            Integer busiyear = Integer.valueOf(new UFDateTime(InvocationInfoProxy.getInstance().getBizDateTime()).getYear());
                            // 预算年:当前单据对应的预算年份
                            Integer nyear = Integer.valueOf(vo.getParentVO().getNyear());

                            int compareTo = nyear.compareTo(busiyear);
                            // 项目累计的预算金额
                            UFDouble yusuan = UFDouble.ZERO_DBL;

                            // 当前单据的金额
                            UFDouble current_data = UFDouble.ZERO_DBL; //初始化
                            // 加上当前单据对应任务状态的
                            if (vo.getParentVO().getTaskstage() == 1) {
                                current_data = child.getAmount_firstup();
                            } else if (vo.getParentVO().getTaskstage() == 3) {
                                current_data = child.getAmount_secondup();
                            }
                            // 当前业务年度取预算最终金额
                            UFDouble busi_data = UFDouble.ZERO_DBL;

                            HashSet<String> exclude = new HashSet<>(); // 需要排除的数据
                            List<BudgetMakeDetailVO> collection = (List<BudgetMakeDetailVO>) getBaseDAO().executeQuery("   SELECT hrpbm_budgetmakedetail.* FROM hrpbm_budgetmakedetail LEFT JOIN hrpbm_budgetmake on hrpbm_budgetmakedetail.PK_BUDGETMAKE = hrpbm_budgetmake.PK_BUDGETMAKE\n" +
                                    "\tWHERE hrpbm_budgetmakedetail.dr = 0 and hrpbm_budgetmake.transtype = '" + vo.getParentVO().getTranstype() + "' AND hrpbm_budgetmakedetail.nyear = '" + busiyear.toString() + "' AND hrpbm_budgetmakedetail.pk_project = '" + pk_project + "' and hrpbm_budgetmakedetail.amount IS NOT NULL ", new BeanListProcessor(BudgetMakeDetailVO.class));

                            if (collection.size() > 0) {
                                Object[] array = collection.toArray(new BudgetMakeDetailVO[0]);
                                for (int i = 0; i < array.length; i++) {
                                    BudgetMakeDetailVO o = (BudgetMakeDetailVO) array[i];
                                    exclude.add(o.getPk_budgetmake());
                                    busi_data = busi_data.add(o.getAmount());
                                    //获取主表 如果任务类型是2上2下 排除对应的1上单据
                                    BudgetMakeVO head_o = (BudgetMakeVO) getBaseDAO().retrieveByPK(BudgetMakeVO.class, o.getPk_budgetmake());
                                    if (head_o.getTaskstage() == 3) {
                                        String pkFirstupbill = head_o.getPk_firstupbill(); //获取对应的1上单据
                                        exclude.add(pkFirstupbill); //排除
                                    }
                                }
                            }
                            exclude.add(vo.getParentVO().getPrimaryKey()); // 添加当前单据pk
                            String inSql = MDDAOUtil.getInSql(exclude.toArray(new String[0]));

                            UFDouble nyear_data = UFDouble.ZERO_DBL;
                            // 当前单据预算年度>=业务年
                            if (compareTo == 0 || compareTo == 1) {
                                Object ny = null;
                                if (vo.getParentVO().getTaskstage() == 1) {
                                    ny = getBaseDAO().executeQuery(
                                            " SELECT SUM(amount_firstup) amount_firstup FROM hrpbm_budgetmakedetail LEFT JOIN hrpbm_budgetmake on hrpbm_budgetmakedetail.pk_budgetmake = hrpbm_budgetmake.pk_budgetmake WHERE hrpbm_budgetmake.taskstage = '1' and hrpbm_budgetmakedetail.dr = 0 and hrpbm_budgetmake.transtype = '"
                                                    + vo.getParentVO().getTranstype()
                                                    + "' AND hrpbm_budgetmakedetail.nyear = '" + nyear
                                                    + "' AND hrpbm_budgetmakedetail.pk_project = '" + pk_project
                                                    + "' and hrpbm_budgetmakedetail.pk_budgetmake not in " + inSql,
                                            new ColumnProcessor());
                                } else if (vo.getParentVO().getTaskstage() == 3) {
                                    ny = getBaseDAO().executeQuery(
                                            " SELECT SUM(amount_secondup) amount_secondup FROM hrpbm_budgetmakedetail LEFT JOIN hrpbm_budgetmake on hrpbm_budgetmakedetail.pk_budgetmake = hrpbm_budgetmake.pk_budgetmake WHERE hrpbm_budgetmake.taskstage = '3' and hrpbm_budgetmakedetail.dr = 0 and hrpbm_budgetmake.transtype = '"
                                                    + vo.getParentVO().getTranstype()
                                                    + "' AND hrpbm_budgetmakedetail.nyear = '" + nyear
                                                    + "' AND hrpbm_budgetmakedetail.pk_project = '" + pk_project
                                                    + "' and hrpbm_budgetmakedetail.pk_budgetmake not in " + inSql,
                                            new ColumnProcessor());
                                }

                                if (ny != null) {
                                    nyear_data = new UFDouble(String.valueOf(ny));
                                }
                            }
                            // 计算一次yusuan
                            yusuan = yusuan.add(current_data).add(busi_data).add(nyear_data);

                            // 历史数据
                            Object history_data = null;
                            // 结果
                            UFDouble result = UFDouble.ZERO_DBL;

                            if (paraString.equals("预算数")) {

                                // 历史年度
                                history_data = getBaseDAO().executeQuery(
                                        " SELECT sum(controlamount) executeamount FROM hrpbctp_busictrldata WHERE dr = 0 and BUSITRANSTYPE = '"
                                                + vo.getParentVO().getTranstype()
                                                + "' and dim3 = '" + pk_project + "'  and dim1 < '"
                                                + busiyear.toString() + "' ",
                                        new ColumnProcessor());

                            } else if (paraString.equals("执行数")) {

                                // 历史年度
                                history_data = getBaseDAO().executeQuery(
                                        " SELECT sum(executeamount) executeamount FROM hrpbctp_busictrldata WHERE dr = 0 and BUSITRANSTYPE = '"
                                                + vo.getParentVO().getTranstype()
                                                + "' and dim3 = '" + pk_project + "'  and dim1 < '"
                                                + busiyear.toString() + "' ",
                                        new ColumnProcessor());

                            }
                            if (history_data != null) {
                                yusuan = yusuan.add(new UFDouble(String.valueOf(history_data)));
                            }
                            result = yusuan.sub(pjtotalcost);

                            if (result.doubleValue() > 0) {
                                throw new BusinessException(
                                        "[" + pjApplHVO.getPjname() + "]项目预算金额:" + new UFDouble(yusuan.doubleValue(), 2)
                                                + "元已超过项目总经费:" + new UFDouble(result.doubleValue(), 2) + "元");
                            }
                        }
                    }
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    public static void check_budgetAdjust(AggBudgetAdjustVO vo) throws BusinessException {
        // 是否安装了项目库 并启用
        if (!isInstalledAndEnabledHrppl())
            return;
        // 支出预算、资本预算及采购预算的编制单（一下，二下） HRPXM001+HRPXM002或HRPXM001+HRPXM003同时启用
        if (vo.getParentVO().getTranstype().equals("BM30-Cxx-AD-YS02")
                || vo.getParentVO().getTranstype().equals("BM30-Cxx-AD-YS03")
                || vo.getParentVO().getTranstype().equals("BM30-Cxx-AD-YS04")) {
            // 判断是否预算编制方案中开启了 项目 维度
            String flag = (String) getBaseDAO()
                    .executeQuery("SELECT hrpbm_budgetschemedetail.ISUSING as flag FROM hrpbm_budgetscheme \r\n"
                            + "left join HRPBM_BUDGETTYPE on hrpbm_budgetscheme.pk_budgettype = HRPBM_BUDGETTYPE.pk_budgettype\r\n"
                            + "left join hrpbm_budgetschemedetail on hrpbm_budgetscheme.PK_BUDGETSCHEME  = hrpbm_budgetschemedetail.PK_BUDGETSCHEME\r\n"
                            + "left join HRPBM_BUDGETDIM on HRPBM_BUDGETDIM.PK_BUDGETDIM = hrpbm_budgetschemedetail.PK_BUDGETDIM\r\n"
                            + " WHERE  hrpbm_budgetscheme.pk_group = '" + vo.getParentVO().getPk_group()
                            + "' and hrpbm_budgetscheme.nyear = '" + vo.getParentVO().getNyear()
                            + "' and HRPBM_BUDGETTYPE.code = '"
                            + vo.getParentVO().getTranstype().substring(vo.getParentVO().getTranstype().length() - 4)
                            + "' and HRPBM_BUDGETDIM.name = '项目'", new ColumnProcessor());

            if (flag.equals("N")) {
                return;
            }
            UFBoolean HRPXM001_Boolean = SysInitQuery.getParaBoolean(vo.getParentVO().getPk_group(), "HRPXM001");
            UFBoolean HRPXM002_Boolean = SysInitQuery.getParaBoolean(vo.getParentVO().getPk_group(), "HRPXM002");
            UFBoolean HRPXM003_Boolean = SysInitQuery.getParaBoolean(vo.getParentVO().getPk_group(), "HRPXM003");

            if (!HRPXM001_Boolean.booleanValue()) { // 如果不开启该参数 则不校验
                return;
            }

            ISuperVO[] children = vo.getChildren(BudgetAdjustDetailVO.class);
            // 表体会存在同一项目不同维度的数据 需要先把同一项目的金额合并 再校验
            HashMap<String, BudgetAdjustDetailVO> hashMap = new HashMap<String, BudgetAdjustDetailVO>();
            // 调整单表体同项目数据合并时 要记录预算号 之后查询批复单数据的时候用来排除
            if (children != null && children.length > 0) {
                for (int i = 0; i < children.length; i++) {
                    BudgetAdjustDetailVO child = (BudgetAdjustDetailVO) children[i];
                    if (child.getStatus() == 3) {
                        continue;
                    }
                    if (hashMap.get(child.getPk_project()) == null) {
                        // 此处用clone的vo 不要修改原数据
                        BudgetAdjustDetailVO clone = (BudgetAdjustDetailVO) child.clone();
                        clone.setDef1(clone.getBudgetno());
                        hashMap.put(child.getPk_project(), clone);
                    } else {
                        BudgetAdjustDetailVO detailVO = hashMap.get(child.getPk_project());
                        detailVO.setAmount_after_adjust(detailVO.getAmount_after_adjust() == null ? UFDouble.ZERO_DBL
                                : detailVO.getAmount_after_adjust()
                                .add(child.getAmount_after_adjust() == null ? UFDouble.ZERO_DBL
                                        : child.getAmount_after_adjust()));
                        detailVO.setDef1(detailVO.getDef1() + "," + child.getBudgetno()); // 记录预算号
                    }
                }
            }

            for (Map.Entry<String, BudgetAdjustDetailVO> entry : hashMap.entrySet()) {
                BudgetAdjustDetailVO child = entry.getValue();
                // 当前单据的调整后金额
                UFDouble current_data = child.getAmount_after_adjust();
                String pk_project = child.getPk_project();
                // 引用自项目库的项目 则项目档案和项目库的主键都是这个
//						PJApplHVO pjApplHVO = dao.findByPk(PJApplHVO.class, pk_project);
                PJApplHVO pjApplHVO = (PJApplHVO) getBaseDAO().retrieveByPK(PJApplHVO.class, pk_project);
                if (pjApplHVO == null) {
//					throw new BusinessException("当前表体引用的项目库项目不存在,请联系项目库相关人员");
                    continue;
                }
                UFDouble pjtotalcost = pjApplHVO.getPjtotalcost(); // 项目库项目总经费
                if (pjtotalcost == null) {
                    pjtotalcost = UFDouble.ZERO_DBL;
                }
                // 业务年
                Integer busiyear = Integer
                        .valueOf(new UFDateTime(InvocationInfoProxy.getInstance().getBizDateTime()).getYear());
                // 当前保存单据的预算年度
                Integer nyear = Integer.valueOf(vo.getParentVO().getNyear());
                //调整单只测调整当年的预算的业务场景
                if (nyear.compareTo(busiyear) != 0) {
                    continue;
                }
                // 当前项目的其它最终预算数  排除掉当前单据关联的编制单
                UFDouble all_amount = UFDouble.ZERO_DBL;
                Object amount = getBaseDAO().executeQuery(
                        " select sum(amount) amount from hrpbm_budgetmakedetail LEFT JOIN hrpbm_budgetmake on hrpbm_budgetmakedetail.pk_budgetmake = hrpbm_budgetmake.pk_budgetmake where hrpbm_budgetmake.dr = 0 AND hrpbm_budgetmake.transtype != 'BM20-Cxx-BD-YS02' and hrpbm_budgetmakedetail.pk_budgettype = '"
                                + vo.getParentVO().getTranstype()
                                .substring(vo.getParentVO().getTranstype().length() - 4)
                                + "' AND hrpbm_budgetmakedetail.nyear = '" + busiyear.toString() + "' AND hrpbm_budgetmakedetail.pk_project = '"
                                + pk_project + "' and hrpbm_budgetmakedetail.pk_budgetmake != '" + vo.getParentVO().getPk_budgetmake() + "' and hrpbm_budgetmakedetail.amount IS NOT NULL ",
                        new ColumnProcessor());

                if (amount != null) {
                    all_amount = new UFDouble(String.valueOf(amount));
                }
                if (pjApplHVO.getTranstype().equals("PL01-Cxx-PJ01")) { // PL01-Cxx-PJ01 常规
                    if (HRPXM002_Boolean.booleanValue()) {

                        // 总数
                        UFDouble total = current_data.add(all_amount);
                        // 结果
                        UFDouble result = total.sub(pjtotalcost);
                        if (result.doubleValue() > 0) {
                            throw new BusinessException(
                                    "[" + pjApplHVO.getPjname() + "]项目调整后预算金额:" + new UFDouble(total.doubleValue(), 2)
                                            + "元已超过项目总经费:" + new UFDouble(result.doubleValue(), 2) + "元");
                        }
                    }
                } else {
                    if (HRPXM003_Boolean.booleanValue()) {
                        String paraString = SysInitQuery.getParaString(vo.getParentVO().getPk_group(), "HRPXM007");

                        // 结果
                        UFDouble result = UFDouble.ZERO_DBL;
                        // 历史数据
                        UFDouble history_data = UFDouble.ZERO_DBL;
                        // 总数
                        UFDouble total = UFDouble.ZERO_DBL;
                        if (paraString.equals("预算数")) {

                            // 历史年度
                            Object history = getBaseDAO().executeQuery(
                                    " SELECT sum(controlamount) controlamount FROM hrpbctp_busictrldata WHERE dr = 0 and TOPBUSICTRLTYPECODE = '"
                                            + vo.getParentVO().getTranstype().substring(
                                            vo.getParentVO().getTranstype().length() - 4)
                                            + "' and dim3 = '" + pk_project + "'  and dim1 < '" + busiyear.toString()
                                            + "' ",
                                    new ColumnProcessor());
                            if (history != null) {
                                history_data = new UFDouble(String.valueOf(history));
                            }

                        } else if (paraString.equals("执行数")) {

                            // 历史年度
                            Object history = getBaseDAO().executeQuery(
                                    " SELECT sum(executeamount) executeamount FROM hrpbctp_busictrldata WHERE dr = 0 and TOPBUSICTRLTYPECODE = '"
                                            + vo.getParentVO().getTranstype().substring(
                                            vo.getParentVO().getTranstype().length() - 4)
                                            + "' and dim3 = '" + pk_project + "'  and dim1 < '" + busiyear.toString()
                                            + "' ",
                                    new ColumnProcessor());
                            if (history != null) {
                                history_data = new UFDouble(String.valueOf(history));
                            }

                        }
                        total = current_data.add(all_amount).add(history_data);
                        result = total.sub(pjtotalcost);

                        if (result.doubleValue() > 0) {
                            throw new BusinessException(
                                    "[" + pjApplHVO.getPjname() + "]项目调整后预算金额:" + new UFDouble(total.doubleValue(), 2)
                                            + "元已超过项目总经费:" + new UFDouble(result.doubleValue(), 2) + "元");
                        }
                    }
                }
            }
        }
    }

    // 预算编制单在提交的时候会自动生成一个预算批复单 并进行保存,但是无法根据状态区分. 此时也会进行该校验,但是这时候的批复单是不存在批复数的 在校验取数的时候会报错
    // 但是批复单修改保存的时候 批复数是必填的 所以如果对应批复数为空 则不进行校验了
    // 使用是否存在主键来判断,编制单生成的批复单保存时不存在主键,但是修改保存时存在
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static void check_budgetReplay(AggBudgetReplyVO vo) throws BusinessException {
        // 是否安装了项目库 并启用
        if (!isInstalledAndEnabledHrppl())
            return;
        // 支出预算、资本预算及采购预算的编制单（一下，二下） HRPXM001+HRPXM002或HRPXM001+HRPXM003同时启用
        if (vo.getParentVO().getTranstype().equals("BM25-Cxx-CD-YS02")
                || vo.getParentVO().getTranstype().equals("BM25-Cxx-CD-YS03")
                || vo.getParentVO().getTranstype().equals("BM25-Cxx-CD-YS04")) {
            // 判断是否预算编制方案中开启了 项目 维度
            String flag = (String) getBaseDAO()
                    .executeQuery("SELECT hrpbm_budgetschemedetail.ISUSING as flag FROM hrpbm_budgetscheme \r\n"
                            + "left join HRPBM_BUDGETTYPE on hrpbm_budgetscheme.pk_budgettype = HRPBM_BUDGETTYPE.pk_budgettype\r\n"
                            + "left join hrpbm_budgetschemedetail on hrpbm_budgetscheme.PK_BUDGETSCHEME  = hrpbm_budgetschemedetail.PK_BUDGETSCHEME\r\n"
                            + "left join HRPBM_BUDGETDIM on HRPBM_BUDGETDIM.PK_BUDGETDIM = hrpbm_budgetschemedetail.PK_BUDGETDIM\r\n"
                            + " WHERE  hrpbm_budgetscheme.pk_group = '" + vo.getParentVO().getPk_group()
                            + "' and hrpbm_budgetscheme.nyear = '" + vo.getParentVO().getNyear()
                            + "' and HRPBM_BUDGETTYPE.code = '"
                            + vo.getParentVO().getTranstype().substring(vo.getParentVO().getTranstype().length() - 4)
                            + "' and HRPBM_BUDGETDIM.name = '项目'", new ColumnProcessor());

            if (flag.equals("N")) {
                return;
            }
            UFBoolean HRPXM001_Boolean = SysInitQuery.getParaBoolean(vo.getParentVO().getPk_group(), "HRPXM001");
            UFBoolean HRPXM002_Boolean = SysInitQuery.getParaBoolean(vo.getParentVO().getPk_group(), "HRPXM002");
            UFBoolean HRPXM003_Boolean = SysInitQuery.getParaBoolean(vo.getParentVO().getPk_group(), "HRPXM003");
            if (!HRPXM001_Boolean.booleanValue()) { // 如果不开启该参数 则不校验
                return;
            }
            // 1下2下 taskstage
            if (vo.getParentVO().getTaskstage() == 2 || vo.getParentVO().getTaskstage() == 4) {

                ISuperVO[] children = vo.getChildren(BudgetReplyDetailVO.class);
                // 表体会存在同一项目不同维度的数据 需要先把同一项目的金额合并 再校验
                HashMap<String, BudgetReplyDetailVO> hashMap = new HashMap<String, BudgetReplyDetailVO>();

                if (children != null && children.length > 0) {
                    for (int i = 0; i < children.length; i++) {
                        BudgetReplyDetailVO child = (BudgetReplyDetailVO) children[i];
                        if (child.getStatus() == 3) {
                            continue;
                        }
                        if (hashMap.get(child.getPk_project()) == null) {
                            // 此处用clone的vo 不要修改原数据
                            BudgetReplyDetailVO clone = (BudgetReplyDetailVO) child.clone();
                            hashMap.put(child.getPk_project(), clone);
                        } else {
                            BudgetReplyDetailVO detailVO = hashMap.get(child.getPk_project());
                            detailVO.setAmount_firstdown(detailVO.getAmount_firstdown() == null ? UFDouble.ZERO_DBL
                                    : detailVO.getAmount_firstdown()
                                    .add(child.getAmount_firstdown() == null ? UFDouble.ZERO_DBL
                                            : child.getAmount_firstdown()));
                            if (vo.getParentVO().getTaskstage() == 4) {
                                detailVO.setAmount_seconddown(
                                        detailVO.getAmount_seconddown() == null ? UFDouble.ZERO_DBL
                                                : detailVO.getAmount_seconddown()
                                                .add(child.getAmount_seconddown() == null ? UFDouble.ZERO_DBL
                                                        : child.getAmount_seconddown()));
                            }
                        }
                    }
                }
//				if(1==1) {
//					throw new BusinessException("test");
//				}

                for (Map.Entry<String, BudgetReplyDetailVO> entry : hashMap.entrySet()) {
                    BudgetReplyDetailVO child = entry.getValue();
                    String pk_project = child.getPk_project();
                    // 引用自项目库的项目 则项目档案和项目库的主键都是这个
//							PJApplHVO pjApplHVO = dao.findByPk(PJApplHVO.class, pk_project);
                    PJApplHVO pjApplHVO = (PJApplHVO) getBaseDAO().retrieveByPK(PJApplHVO.class, pk_project);
                    if (pjApplHVO == null) {
//						throw new BusinessException("当前表体引用的项目库项目不存在,请联系项目库相关人员");
                        continue;
                    }
                    UFDouble pjtotalcost = pjApplHVO.getPjtotalcost(); // 项目库项目总经费
                    if (pjtotalcost == null) {
                        pjtotalcost = UFDouble.ZERO_DBL;
                    }
                    if (pjApplHVO.getTranstype().equals("PL01-Cxx-PJ01")) { // PL01-Cxx-PJ01 常规
                        if (HRPXM001_Boolean.booleanValue() && HRPXM002_Boolean.booleanValue()) {
                            // 预算编制单引用了项目库的“常规项目”进行预算编制，保存时要进行验证：当年预算编制金额不能超过项目库项目总经费(pjtotalcost)

                            // 取当前保存单据的预算年度
                            Integer nyear = Integer.valueOf(vo.getParentVO().getNyear());

                            // 项目对应的预算编制金额
                            Map<String, Object> map = (Map<String, Object>) getBaseDAO().executeQuery(
                                    " SELECT sum(hrpbm_budgetreplydetail.amount_firstdown) first,sum(hrpbm_budgetreplydetail.amount_seconddown) second \r\n"
                                            + " FROM hrpbm_budgetreplydetail LEFT JOIN hrpbm_budgetreply on hrpbm_budgetreplydetail.pk_budgetreply = hrpbm_budgetreply.pk_budgetreply \r\n"
                                            + " where hrpbm_budgetreplydetail.pk_project = '" + pk_project
                                            + "' AND hrpbm_budgetreply.TRANSTYPE = '" + vo.getParentVO().getTranstype()
                                            + "' AND hrpbm_budgetreply.taskstage = '"
                                            + vo.getParentVO().getTaskstage().toString()
                                            + "' and hrpbm_budgetreplydetail.nyear = '" + nyear
                                            + "' AND hrpbm_budgetreplydetail.PK_BUDGETREPLY != '"
                                            + vo.getParentVO().getPrimaryKey() + "'",
                                    new MapProcessor());

                            // 项目预算金额
                            UFDouble yusuan = UFDouble.ZERO_DBL;
                            if (vo.getParentVO().getTaskstage() == 2) {
                                if (StringUtils.isEmpty(vo.getParentVO().getPrimaryKey())) {
                                    continue;
                                }
                                Object object = map.get("first");
                                if (object != null) {
                                    // 加上当前单据的
                                    yusuan = new UFDouble(object.toString()).add(child.getAmount_firstdown());
                                } else {
                                    // 只算当前单据
                                    yusuan = child.getAmount_firstdown();
                                }
                            } else if (vo.getParentVO().getTaskstage() == 4) {
                                if (StringUtils.isEmpty(vo.getParentVO().getPrimaryKey())) {
                                    continue;
                                }
                                Object object = map.get("second");
                                if (object != null) {
                                    // 加上当前单据的
                                    yusuan = new UFDouble(object.toString()).add(child.getAmount_seconddown());
                                } else {
                                    // 只算当前单据
                                    yusuan = child.getAmount_seconddown();
                                }
                            }
                            UFDouble result = UFDouble.ZERO_DBL;
                            result = yusuan.sub(pjtotalcost);
                            if (result.doubleValue() > 0) {
                                throw new BusinessException("项目预算金额" + new UFDouble(yusuan.doubleValue(), 2)
                                        + "元已超过项目总经费" + new UFDouble(result.doubleValue(), 2) + "元");
                            }
                        }
                    } else { // 非常规项目的校验
                        if (HRPXM001_Boolean.booleanValue() && HRPXM003_Boolean.booleanValue()) {
                            String paraString = SysInitQuery.getParaString(vo.getParentVO().getPk_group(), "HRPXM007");

                            // 累计预算金额不能超过项目库项目总经费
                            // 业务年度:业务日期的年度
                            Integer busiyear = Integer.valueOf(
                                    new UFDateTime(InvocationInfoProxy.getInstance().getBizDateTime()).getYear());
                            // 预算年度:当前保存单据对应的预算年度
                            Integer nyear = Integer.valueOf(vo.getParentVO().getNyear());

                            int compareTo = nyear.compareTo(busiyear);
                            // 项目预算金额
                            UFDouble yusuan = UFDouble.ZERO_DBL;

                            // 当前单据的预算金额
                            UFDouble current_data = UFDouble.ZERO_DBL;//初始化
                            // 加上当前单据的
                            if (vo.getParentVO().getTaskstage() == 2) {
                                if (StringUtils.isEmpty(vo.getParentVO().getPrimaryKey())) {
                                    continue;
                                }
                                current_data = child.getAmount_firstdown();
                            } else if (vo.getParentVO().getTaskstage() == 4) {
                                if (StringUtils.isEmpty(vo.getParentVO().getPrimaryKey())) {
                                    continue;
                                }
                                current_data = child.getAmount_seconddown();
                            }

                            // 当前业务年度取预算最终金额
                            UFDouble busi_data = UFDouble.ZERO_DBL;
                            // 当前业务年获取最终预算 要去编制单取,批复单不会回写最终预算
                            HashSet<String> exclude = new HashSet<>();

                            List<BudgetReplyDetailVO> collection = (List<BudgetReplyDetailVO>) getBaseDAO().executeQuery(" SELECT hrpbm_budgetreplydetail.* FROM hrpbm_budgetreplydetail LEFT JOIN hrpbm_budgetreply on hrpbm_budgetreplydetail.pk_budgetreply = hrpbm_budgetreply.pk_budgetreply\n" +
                                    "\tWHERE hrpbm_budgetreplydetail.dr = 0 and hrpbm_budgetreply.transtype = '" + vo.getParentVO().getTranstype() + "' and hrpbm_budgetreplydetail.nyear = '" + busiyear + "' and hrpbm_budgetreplydetail.pk_project = '" + pk_project + "' ", new BeanListProcessor(BudgetReplyDetailVO.class));
                            //记录统计过的  表体多行的时候会查出来多次
                            HashSet<String> count_pk = new HashSet<>();

                            if (collection.size() > 0) {
                                Object[] array = collection.toArray(new BudgetReplyDetailVO[0]);
                                for (int i = 0; i < array.length; i++) {
                                    BudgetReplyDetailVO o = (BudgetReplyDetailVO) array[i];
                                    if (count_pk.contains(o.getPk_budgetreply())) {
                                        continue;
                                    }
                                    //统计过的就加入集合
                                    count_pk.add(o.getPk_budgetreply());
                                    //获取主表  根据任务阶段 去查询
                                    BudgetReplyVO head_o = (BudgetReplyVO) getBaseDAO().retrieveByPK(BudgetReplyVO.class, o.getPk_budgetreply());
                                    //获取任务信息 判断任务是2上2下 还是1上1下
                                    Budgettask budgettask = (Budgettask) getBaseDAO().retrieveByPK(Budgettask.class, head_o.getPk_budgettask());

                                    Collection budgetmakeAggVo = null;
                                    if (budgettask.getTaskprocess() == 1 && head_o.getTaskstage() == 2) { //1下
                                        budgetmakeAggVo = MDPersistenceService.lookupPersistenceQueryService().queryBillOfVOByCondWithOrder(AggBudgetMakeVO.class, " pk_budgetmake = '" + head_o.getPk_firstupbill() + "' and hrpbm_budgetmake.transtype != 'BM20-Cxx-BD-YS02' ", false, false, null);
                                    } else if (budgettask.getTaskprocess() == 2 && head_o.getTaskstage() == 4) { //2下
                                        //2下的任务直接排除掉1下的单据
                                        exclude.add(head_o.getPk_firstdownbill());
                                        budgetmakeAggVo = MDPersistenceService.lookupPersistenceQueryService().queryBillOfVOByCondWithOrder(AggBudgetMakeVO.class, " pk_budgetmake = '" + head_o.getPk_secondupbill() + "' and hrpbm_budgetmake.transtype != 'BM20-Cxx-BD-YS02'", false, false, null);
                                    }

                                    if (budgetmakeAggVo != null && budgetmakeAggVo.size() > 0) {
                                        Object[] arrayAggvo = budgetmakeAggVo.toArray(new AggBudgetMakeVO[0]);
                                        for (int j = 0; j < arrayAggvo.length; j++) {
                                            AggBudgetMakeVO aggo = (AggBudgetMakeVO) arrayAggvo[j];

                                            ISuperVO[] makedetails = aggo.getChildren(BudgetMakeDetailVO.class);
                                            if (makedetails != null && makedetails.length > 0) {
                                                for (int k = 0; k < makedetails.length; k++) {
                                                    BudgetMakeDetailVO iSuperVO = (BudgetMakeDetailVO) makedetails[k];
                                                    if (iSuperVO.getAmount() == null) {
                                                        busi_data = busi_data.add(UFDouble.ZERO_DBL);
                                                    } else {
                                                        busi_data = busi_data.add(iSuperVO.getAmount());
                                                        exclude.add(o.getPk_budgetreply());
                                                    }

//													if (o.getBudgetno() == iSuperVO.getBudgetno()) { //判断是否是新增的维度 是否要过滤
//														exclude.add(o.getPk_budgetreply());
//													}
                                                }
                                            }
                                        }
                                    }
                                }
                            }

                            UFDouble nyear_data = UFDouble.ZERO_DBL;
                            if (compareTo == 0 || compareTo == 1) { // 当前单据预算年度>=业务年
                                exclude.add(vo.getParentVO().getPrimaryKey());
                                String inSql = MDDAOUtil.getInSql(exclude.toArray(new String[0]));

                                // 当前业务年度取预算最终金额 按预算大类+年度+项目进行汇总统计（可能是多单）
                                Object ny = null;
                                if (vo.getParentVO().getTaskstage() == 2) {
                                    ny = getBaseDAO().executeQuery(
                                            " SELECT SUM(amount_firstdown) amount_firstdown FROM  hrpbm_budgetreplydetail LEFT JOIN hrpbm_budgetreply on hrpbm_budgetreplydetail.PK_BUDGETREPLY = hrpbm_budgetreply.PK_BUDGETREPLY WHERE hrpbm_budgetreply.taskstage = '2' and hrpbm_budgetreplydetail.dr = 0 and hrpbm_budgetreply.transtype = '"
                                                    + vo.getParentVO().getTranstype()
                                                    + "' AND hrpbm_budgetreplydetail.nyear >= '" + busiyear.toString()
                                                    + "' AND hrpbm_budgetreplydetail.pk_project = '" + pk_project
                                                    + "' and hrpbm_budgetreplydetail.PK_BUDGETREPLY not in " + inSql,
                                            new ColumnProcessor());
                                } else if (vo.getParentVO().getTaskstage() == 4) {
                                    ny = getBaseDAO().executeQuery(
                                            " SELECT SUM(amount_seconddown) amount_seconddown FROM  hrpbm_budgetreplydetail LEFT JOIN hrpbm_budgetreply on hrpbm_budgetreplydetail.PK_BUDGETREPLY = hrpbm_budgetreply.PK_BUDGETREPLY WHERE hrpbm_budgetreply.taskstage = '4' and hrpbm_budgetreplydetail.dr = 0 and hrpbm_budgetreply.transtype = '"
                                                    + vo.getParentVO().getTranstype()
                                                    + "' AND hrpbm_budgetreplydetail.nyear >= '" + busiyear.toString()
                                                    + "' AND hrpbm_budgetreplydetail.pk_project = '" + pk_project
                                                    + "' and hrpbm_budgetreplydetail.PK_BUDGETREPLY not in " + inSql,
                                            new ColumnProcessor());
                                }

                                if (ny != null) {
                                    nyear_data = new UFDouble(String.valueOf(ny));
                                }
                            }

                            // 计算一次yusuan
                            yusuan = yusuan.add(current_data).add(busi_data).add(nyear_data);

                            // 历史数据
                            Object history_data = null;
                            // 结果
                            UFDouble result = UFDouble.ZERO_DBL;

                            //预算执行监控里的执行数是跟编制单关联的  所以对应的批复交易类型要转为编制交易类型
                            String transtype = null;
                            switch (vo.getParentVO().getTranstype()) {
                                case "BM25-Cxx-CD-YS02":
                                    transtype = "BM20-Cxx-CD-YS02";
                                    break;
                                case "BM25-Cxx-CD-YS03":
                                    transtype = "BM20-Cxx-CD-YS03";
                                    break;
                                case "BM25-Cxx-CD-YS04":
                                    transtype = "BM20-Cxx-CD-YS04";
                                    break;
                            }

                            if (paraString.equals("预算数")) {

                                // 历史年度
                                history_data = getBaseDAO().executeQuery(
                                        " SELECT sum(controlamount) executeamount FROM hrpbctp_busictrldata WHERE dr = 0 and BUSITRANSTYPE = '"
                                                + transtype
                                                + "' and dim3 = '" + pk_project + "'  and dim1 < '"
                                                + busiyear + "' ",
                                        new ColumnProcessor());

                            } else if (paraString.equals("执行数")) {

                                // 历史年度
                                history_data = getBaseDAO().executeQuery(
                                        " SELECT sum(executeamount) executeamount FROM hrpbctp_busictrldata WHERE dr = 0 and BUSITRANSTYPE = '"
                                                + transtype
                                                + "' and dim3 = '" + pk_project + "'  and dim1 < '"
                                                + busiyear + "' ",
                                        new ColumnProcessor());

                            }
                            if (history_data != null) {
                                yusuan = yusuan.add(new UFDouble(String.valueOf(history_data)));
                            }
                            result = yusuan.sub(pjtotalcost);
                            if (result.doubleValue() > 0) {
                                throw new BusinessException(
                                        "[" + pjApplHVO.getPjname() + "]项目预算金额:" + new UFDouble(yusuan.doubleValue(), 2)
                                                + "元已超过项目总经费:" + new UFDouble(result.doubleValue(), 2) + "元");
                            }
                        }
                    }
                }
            }
        }
    }

}
